home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Dev / ACE / utils / UppercACEr / UppercACEr.b < prev    next >
Text File  |  1994-10-22  |  10KB  |  365 lines

  1. '******************************************************
  2. '*                    UppercACEr                      *
  3. '*       by K.Veijalainen (veijalai@cc.lut.fi)        *
  4. '*                                                    *
  5. '*        This program is SLOW. But it works.         *
  6. '*                                                    *
  7. '* 6.7.'94 - Work started(gettin' familiar with ACE)  *
  8. '*           An almost working but S.L.O.W version    *
  9. '*           finished...                              *
  10. '* 7.7     - Added check whether it's substring that  *
  11. '*           is found or a real reserved word         *
  12. '*           Optimized code a bit                     *
  13. '*           Added check for CTRL-C                   *
  14. '*           Removed bug with empty line check        *
  15. '*           Added check for strings in "" and        *
  16. '*           comments within {}-brackets.             *
  17. '*           Added 'QUIET'-parameter                  *
  18. '*           Added 'DEBUG'-parameter                  *
  19. '* 8.7     - Partial rewrite :-)                      *
  20. '*           Fixed & sped up string-checking          *
  21. '*           -''-            {}-comment-checking      *
  22. '* ?.7-11.7- Rewrite. Bugfixes by Ede                 *
  23. '* 20.7    - _jumppi-table.                           *
  24. '* 22.7    - Bugfixes                                 *
  25. '* 23.7    - Bugfix   - removed DEBUG-option          *
  26. '* 24.7    - Wrote sucky docs.                        *
  27. '* 26.7    - Fixed a division-by-zero error which     *
  28. '*           occurred during speed info' calculation  *
  29. '*           for short ACE programs where btime!=0.   *
  30. '*           (DB)                                     *
  31. '* 27.7    - removal of leftmost char in _res$()      *
  32. '* 18.8    - empty line bug in skip_block_comment fixd*
  33. '* 15.10   - Reserved word file must now be in s:.    *
  34. '******************************************************
  35.  
  36. 'These are used for the _jumppi()-table
  37. CONST _first=0,_last=1
  38.  
  39. 'Get the parameters
  40. IF ARGCOUNT<2 THEN
  41.     PRINT "You must give at least 2 parameters."
  42.     PRINT "Usage: "+ARG$(0)+" <inputfile>[.b] <outputfile>[.b] [QUIET]"
  43.     PRINT "The .b-extension is optional. If it's missing, it will be added."
  44.     STOP
  45. ELSE
  46.     _infile$=ARG$(1)
  47.     _outfile$=ARG$(2)
  48.     IF UCASE$(RIGHT$(_infile$,2))<>".B"  THEN _infile$=_infile$+".b"
  49.     IF UCASE$(RIGHT$(_outfile$,2))<>".B" THEN _outfile$=_outfile$+".b"
  50.     _quiet=0 :REM defaults
  51.     'This loop is made for easy addition of parameters in future
  52.     FOR z=3 TO 3
  53.         IF UCASE$(ARG$(z))="QUIET" AND _quiet=0 THEN _quiet=1
  54.     NEXT
  55. END IF
  56.  
  57. ON BREAK GOTO lopetus
  58. BREAK ON
  59.  
  60. 'Globally declare all variables as short int
  61. DEFINT a-z,_
  62.  
  63. DECLARE SUB msg(_message$,_lf)
  64. DECLARE SUB match_n_replace(mm$)
  65. DECLARE SUB skip_spaces
  66. DECLARE SUB find_word
  67. DECLARE SUB skip_block_comment
  68. DECLARE SUB openfiles
  69. DECLARE SUB _readline
  70.  
  71. msg("Reading the reserved word index..",0)
  72. n=0
  73. 'Check the number of reserved words in the index file
  74. OPEN "I",#1,"s:UppercACEr.Reserved"
  75. 'Check whether _infile exists
  76. IF HANDLE(1) = 0& THEN
  77.     PRINT "Could not open UppercACEr.Reserved!"
  78.     PRINT "Check that this file exists in "+ARG$(0)+CHR$(39)+"s current directory."
  79.     STOP
  80. END IF
  81. WHILE NOT EOF(1)
  82.     LINE INPUT #1,t$
  83.     'Only inc n if the 1st char of t$ is not '
  84.     IF PEEK(@t$)<>39 THEN ++n
  85. WEND
  86. CLOSE #1
  87. 'Alloc mem and dim the _res$()-array
  88. CONST StrSize=11 : REM the max reserved word length is 10! (ACE 2.0)
  89. myStrArrayAddr& = ALLOC(n*StrSize)
  90. 'This memory is automatically freed by ACE when the program exits
  91. IF myStrArrayAddr& = 0& THEN
  92.     PRINT "..Could not allocate";n*StrSize;" bytes of memory!"
  93.     STOP
  94. END IF
  95. DIM _res$(1) SIZE StrSize ADDRESS myStrArrayAddr&
  96. '..read strings from file
  97. 'Dim the jump location table
  98. DIM _jumppi(1,25)
  99. 'Clear the table's START-locations.
  100. FOR x=0 TO 25
  101.     _jumppi(_first,x)=-1
  102. NEXT
  103. oa=-1 :REM make sure that oa<>a the 1st TIME we enter the loop...
  104. OPEN "I",#1,"s:UppercACEr.Reserved"
  105. FOR x=0 TO n
  106.     'The .Reserved-file can contain comment lines starting with a ' (chr$(39))
  107.     REPEAT
  108.         LINE INPUT #1,t$
  109.         'a is the ascii code of the 1st letter of t$
  110.         a=PEEK(@t$)
  111.     UNTIL a<>39
  112.     a=a-65
  113.     IF a>-1 AND a<26 THEN
  114.         'Cut the 1st character - we KNOW what the 1st letter is from
  115.         'the location in the _jumppi-table, so string-match checking
  116.         'later on will be a tiny bit faster.
  117.         l=LEN(t$)-1
  118.         _res$(x)=UCASE$(RIGHT$(t$,l))
  119.         IF oa<>a THEN
  120.             _jumppi(_first,a)=x :REM beginning of words starting with different char
  121.         END IF
  122.         _jumppi(_last,a)=x :REM This 'pointer' moves TO the last word...
  123.     END IF
  124.     oa=a
  125. NEXT
  126. CLOSE #1
  127. msg(".."+STR$(n+1)+" words loaded.",1)
  128.  
  129. 'Open the files
  130. OPEN "I",#1,_infile$
  131. IF HANDLE(1)=0& THEN
  132.     PRINT "Could not open "+_infile$+"!"
  133.     STOP
  134. END IF
  135. OPEN "O",#2,_outfile$
  136.  
  137. COLOR 2,1
  138. msg(" UppercACEr v0.33 ",0)
  139. COLOR 1,3
  140. msg(" by K.Veijalainen (veijalai@cc.lut.fi) ",1)
  141. COLOR 1,0
  142. msg("Converting "+_infile$+" --> "+_outfile$,1)
  143.  
  144. '*******************************************************************************
  145. 'Main
  146. 'Read the lines and parse them.
  147. _lines=0:_words=0
  148. btime!=TIMER
  149. WHILE NOT EOF(1)
  150.     _readline
  151.     'Skip if the line is empty
  152.     IF LEN(t$)=0 THEN
  153.         t$=""
  154.     ELSE
  155.         'Search the point where real stuff begins
  156.         y=1 :REM reset the location "pointer"
  157.         'Skip the initial indention
  158.         WHILE ASC(MID$(t$,y,1))<33 AND y<LEN(t$)+1
  159.             'as long as there are spaces/tabs
  160.             ++y
  161.         WEND
  162.         'Was the line just full of BS spaces/tabs?
  163.         IF y>LEN(t$) THEN
  164.             t$=""
  165.         ELSE
  166.             'Let's skip comment lines - Check for "'"-character in the beginning
  167.             IF MID$(t$,y,1)<>CHR$(39) THEN
  168.                 'Whoah! We got this far!
  169.                 REPEAT
  170.                     'Skip spaces between words
  171.                     skip_spaces
  172.                     'Find the next word on line
  173.                     m$=""
  174.                     oy=y : REM oy points TO the beginning of m$ now!
  175.                     find_word
  176.                     'M$ now is the WORD we found above
  177.                     'Check if there is a match and do the dirty deed
  178.                     match_n_replace(m$)
  179.                 UNTIL y>LEN(t$)
  180.             END IF
  181.         END IF
  182.     END IF
  183.     'This prevents oddness...
  184.     IF t$="" THEN
  185.         PRINT #2,CHR$(10);
  186.     ELSE
  187.         PRINT #2,t$
  188.     END IF
  189. WEND
  190. btime!=TIMER-btime!
  191.  
  192. BREAK OFF
  193.  
  194. 'Close the files
  195. CLOSE #1
  196. CLOSE #2
  197.  
  198. 'Display some info
  199. msg("# of lines in source:"+STR$(_lines),1)
  200. msg("# of reserved words :"+STR$(_words),1)
  201. IF btime! <> 0 THEN
  202.     msg("Took"+STR$(btime!)+" seconds. Speed:"+STR$(_lines/btime!)+" l/s.",1)
  203. END IF
  204. msg("All done.",1)
  205. STOP
  206.  
  207. '*******************************************************************************
  208. 'Procedures here...
  209.  
  210. 'This procedure prints line of text with optional linefeed. Takes the
  211. 'global variable '_quiet' into account - if _quiet is true, nothing is printed.
  212. SUB msg(_message$,_lf)
  213.     SHARED _quiet
  214.     IF _quiet=0 THEN
  215.         IF _lf=1 THEN
  216.                 PRINT _message$
  217.         ELSE
  218.                 PRINT _message$;
  219.         END IF
  220.     END IF
  221. END SUB
  222.  
  223. 'Speed this thing up!
  224. SUB match_n_replace(mm$)
  225.     SHARED _res$,t$,y,_words,n,oy,_jumppi
  226.     l=LEN(mm$)
  227.     'This check eliminates one-letter variables etc...
  228.     IF l>1 THEN
  229.         mm$=UCASE$(mm$)
  230.         'Location in _jumppi-table
  231.         a=peek(@mm$)-65
  232.         'Is the word we are looking for possibly a reserved word?
  233.         '(They all seem to start with a-z, NEVER with a number or _ or such...)
  234.         'Also check, whether the length is more than 1 (all reserved words are
  235.         'at least 2 characters long.
  236.         IF a>-1 AND a<26 THEN
  237.             'Min and Max boundaries
  238.             x1=_jumppi(_first,a)
  239.             'if x1 is -1, then there are no words starting with chr$(a+65)
  240.             IF x1>-1 THEN
  241.                 x2=_jumppi(_last,a)
  242.                 'Crop off the leftmost character, because the words in _res$()-
  243.                 'table also are cropped.
  244.                 mm$=RIGHT$(mm$,l-1)
  245.                 FOR x=x1 TO x2
  246.                     IF mm$=_res$(x) THEN
  247.                         'Uppercase the sucker.
  248.                         'oy points to the beginning of the word.
  249.                         'y points to the end of the word +1
  250.                         'l is the length of the original mm$
  251.                         u$=t$
  252.                         't$=left$(u$,oy-1)+ucase$(mid$(u$,oy,l))+right$(u$,len(u$)-y+1)
  253.                         t$=LEFT$(u$,oy-1)+UCASE$(MID$(u$,oy,l))+MID$(u$,y)
  254.                         ++_words
  255.                         'Make sure the rest is skipped if a REM is found
  256.                         IF mm$="EM" THEN y=LEN(t$)+2
  257.                         EXIT FOR
  258.                     END IF
  259.                 NEXT
  260.             END IF
  261.         END IF
  262.     END IF
  263. END SUB
  264.  
  265. 'This sub "collects" the next word into string m$ from previously
  266. 'found location y onwards and leaves y pointing to the 1st non-alphanumeric
  267. 'character or the end of the line.
  268. SUB find_word
  269.     SHARED y,t$,m$
  270.     WHILE y<LEN(t$)+1
  271.         a=PEEK(@t$+y-1)
  272.         IF a<48 OR (a>57 AND a<65) OR (a>90 AND a<>95 AND a<97) OR a>122 THEN
  273.                 exit sub
  274.         ELSE
  275.                 'as long as character IS alphanumeric, add it to string
  276.                 m$=m$+chr$(a)
  277.                 'Move pointer to next char
  278.                 ++y
  279.         END IF
  280.     WEND
  281. END SUB
  282.  
  283. 'Skips the spaces and stuff between words, plus strings and block
  284. 'comments.
  285. 'This checks whether c$ is alphanumeric or not, AND skips
  286. 'strings and block comments. NOTE! It does not matter is t$
  287. 'is changed within this sub.
  288. SUB skip_spaces
  289.     SHARED y,t$
  290.     WHILE y<LEN(t$)+1
  291.         a=PEEK(@t$+y-1)
  292.         'String skipping
  293.         IF a=34 THEN
  294.             'This should _ONLY_ be executed from skip_spaces!!
  295.             ++y
  296.             WHILE PEEK(@t$+y-1)<>34 AND y<LEN(t$)+1
  297.                 ++y
  298.             WEND
  299.             ++y
  300.         ELSE
  301.             'Is there a {}-comment? Can be spread on many lines.
  302.             'The comment ends at a matching } or at the end of the source.
  303.             '{-123  }-125
  304.             IF a=123 THEN
  305.                 skip_block_comment
  306.             ELSE
  307.                 IF (a>47 AND a<58) OR (a>64 AND a<91) OR a=95 OR (a>96 AND a<123) THEN
  308.                     'Ok ok... so here we are: beginning of another word found....
  309.                     exit sub
  310.                 else
  311.                     ++y
  312.                 END IF
  313.             END IF
  314.         END IF
  315.     WEND
  316. END SUB
  317.  
  318. SUB skip_block_comment
  319.     SHARED y,t$,_lines
  320.     ++y
  321.     loopz:
  322.     WHILE ASC(MID$(t$,y,1))<>125 AND y<LEN(t$)+1
  323.         ++y
  324.     WEND
  325.     'Is there need to read a new line? ARGH!
  326.     IF y>LEN(t$) THEN
  327.         'store the old line...
  328.         IF t$="" THEN
  329.             PRINT #2,CHR$(10);
  330.         ELSE
  331.             PRINT #2,t$
  332.         END IF
  333.         IF NOT EOF(1) THEN
  334.             _readline
  335.             y=1 :REM reset the location pointer
  336.             GOTO loopz:
  337.         ELSE
  338.             y=LEN(t$)+2 : REM make sure nothing else is done in Main
  339.         END IF
  340.     END IF
  341.     ++y
  342. END SUB
  343.  
  344. 'Reads a line of source and prints the number of lines processed.
  345. 'Also removes some crap.
  346. SUB _readline
  347.     SHARED t$,_lines,_quiet
  348.     LINE INPUT #1,t$
  349.     ++_lines
  350.     'MSG() is not used to speed things up
  351.     IF _quiet=0 THEN
  352.         IF _lines MOD 10=0 THEN PRINT _lines;:PRINT CHR$(13);
  353.     END IF
  354.     'Remove needless spaces/tabs after a line
  355.     WHILE ASC(RIGHT$(t$,1))<33 AND LEN(t$)>0
  356.         t$=LEFT$(t$,LEN(t$)-1)
  357.     WEND
  358. END SUB
  359.  
  360. lopetus:
  361.     PRINT:PRINT "Aborted!"
  362.     CLOSE #1
  363.     CLOSE #2
  364.     STOP
  365.